package com.billow.net.rtmp
{
	import flash.events.EventDispatcher;
	import flash.net.ObjectEncoding;
	import flash.utils.ByteArray;
	import flash.utils.Dictionary;

	internal class RtmpEncoder
	{
		private var _buffer:ByteArray;
		
		private var _oldRtmpBodyType:Vector.<uint>;
		private var _oldRtmpBodySize:Vector.<uint>;
		private var _oldStreamTimeStamp:Vector.<uint>;
		private var _oldStreamChannel:Vector.<int>;
		
		private var _headerSize:uint;
		private var _headerFlag:uint;
		private var _chunkSize:uint;
		private var _remaining:uint;
		
		public function RtmpEncoder()
		{
			_buffer = new ByteArray();
			_oldRtmpBodyType = new Vector.<uint>(64);
			_oldRtmpBodySize = new Vector.<uint>(64);
			_oldStreamTimeStamp = new Vector.<uint>(64);
			_oldStreamChannel = new Vector.<int>(64);
			
			for(var i:int = 0; i < 64; i ++)
			{
				_oldRtmpBodyType[i] = 0;
				_oldRtmpBodySize[i] = 0;
				_oldStreamTimeStamp[i] = 0;
				_oldStreamChannel[i] = -1;
			}
		}
		
		
		
		public function process(packet:RtmpPacket):ByteArray
		{
			_buffer.clear();
			
			if(_oldStreamChannel[packet.rtmpChannel] == packet.streamChannel && packet.rtmpChannel != 0x02)
			{
				_headerSize = 8;
				_headerFlag = 0x40;
				
				if(_oldRtmpBodyType[packet.rtmpChannel] == packet.rtmpBodyType && _oldRtmpBodySize[packet.rtmpChannel] == packet.rtmpBodySize)
				{
					_headerSize = 4;
					_headerFlag = 0x80;
					
					if(_oldStreamTimeStamp[packet.rtmpChannel] == packet.streamTimeStamp)
					{
						_headerSize = 1;
						_headerFlag = 0xC0;
					}
				}
			}
			else
			{
				_headerSize = 12;
				_headerFlag = 0x00;
			}
			
			_oldRtmpBodyType[packet.rtmpChannel] = packet.rtmpBodyType;
			_oldRtmpBodySize[packet.rtmpChannel] = packet.rtmpBodySize;
			_oldStreamTimeStamp[packet.rtmpChannel] = packet.streamTimeStamp;
			_oldStreamChannel[packet.rtmpChannel] = packet.streamChannel;
			
			var first:uint = _headerFlag | (packet.rtmpChannel & 0x3F);
			_buffer.writeByte(first);
			
			if(_headerSize > 1)
			{
				_buffer.writeShort((packet.streamTimeStamp >> 8) & 0xFFFF);
				_buffer.writeByte(packet.streamTimeStamp & 0xFF);
				
				if(_headerSize > 4)
				{
					_buffer.writeShort((packet.rtmpBodySize >> 8) & 0xFFFF);
					_buffer.writeByte(packet.rtmpBodySize & 0xFF);
					_buffer.writeByte(packet.rtmpBodyType);
					
					if(_headerSize > 8)
					{
						_buffer.writeByte(packet.streamChannel & 0xFF);
						_buffer.writeByte((packet.streamChannel >> 8) && 0xFF);
						_buffer.writeByte((packet.streamChannel >> 16) && 0xFF);
						_buffer.writeByte((packet.streamChannel >> 24) && 0xFF);
					}
				}
			}
			
			_chunkSize = (packet.rtmpBodyType == 0x08 ? 65 : 128);
			_remaining = packet.rtmpBodySize;
			
			while(_remaining > 0)
			{
				var size:uint = (_remaining < _chunkSize ? _remaining : _chunkSize);
				_buffer.writeBytes(packet.rtmpBody, packet.rtmpBodySize - _remaining, size);
				_remaining -= size;
				if(_remaining > 0) _buffer.writeByte(first | 0xC0);
			}
			
			_buffer.position = 0;
			return _buffer;
		}
	}
}